package com.zlq.easydbutils.factory;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.Properties;

import com.zlq.easydbutils.EasyDataSource;
import com.zlq.easydbutils.Runner;
import com.zlq.easydbutils.annotation.StratTransaction;
import com.zlq.easydbutils.exception.EasyDBUtilsException;
/**
 * EasyDBUtils的核心——EasyFactory
 * @author lunqi
 *
 */
public class EasyFactory {
	
	public static final Properties prop = new Properties();
	
	//获取数据源的接口，用户要自己根据自己的数据源来写实现类
	private static EasyDataSource eds = null;
	
	//本地线程，用于存放事务管理的连接
	private static final ThreadLocal<Connection> local = new ThreadLocal<Connection>();
	
	//静态代码快实现配置文件的加载
	static{
		try {
			prop.load(EasyFactory.class.getClassLoader().getResourceAsStream("/easyDBUtils.properties"));
		} catch (IOException e) {
			throw new EasyDBUtilsException("easyDBUtils.properties配置文件路径或名称错误！");
		}
		try {
			eds =  (EasyDataSource) Class.forName(prop.getProperty("EasyDataSource")).newInstance();
		} catch (Exception e) {
			throw new EasyDBUtilsException("配置文件配置EasyDataSource错误！");
		}
	} 
	
	@SuppressWarnings("unchecked")
	public static <T> T newServiceInstance(Class<T> clazz) {
		//根据配置文件加载业务层字节码文件
		try {
			clazz = (Class<T>) Class.forName(prop.getProperty(clazz.getSimpleName()));
		} catch (ClassNotFoundException e) {
			throw new EasyDBUtilsException("配置文件配置错误！");
		}
		T	t_class = null;
		//实例化业务层对象
		try {
			t_class =clazz.newInstance();
		} catch (Exception e) {
			throw new EasyDBUtilsException("配置文件配置错误！");
		}
		 final T t = t_class;
		 //动态代理实现注解管理事务
		return (T) Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				Connection conn = eds.getConnection();
				//加了事务注解
				local.set(conn);
				if (method.getAnnotation(StratTransaction.class)!=null) {
					//开启事务
					conn.setAutoCommit(false);
					try{
						//执行方法
						Object obj =  method.invoke(t, args);
						//提交事务
						local.get().commit();
						return obj;
					}catch(Exception e){
						//回滚
						local.get().rollback();
						throw new EasyDBUtilsException("持久层出现异常！回滚事务");
					}finally{
						//返回连接到连接池
						local.get().close();
						local.remove();
					}
				}else{
					//如果没有写注解
					try{
						return method.invoke(t, args);
					}catch(Exception e){
						throw new EasyDBUtilsException("持久层出现异常！事务未回滚");
					}finally{
						local.get().close();
						local.remove();
					}
				}
			}
		});
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T newDaoInstance(Class<T> clazz){
		try {
			clazz = (Class<T>) Class.forName(prop.getProperty(clazz.getSimpleName()));
		} catch (ClassNotFoundException e) {
			throw new EasyDBUtilsException("配置文件配置错误！");
		}
		 T t = null;
			try {
				t = clazz.newInstance();
			} catch (Exception e) {
				throw new EasyDBUtilsException("配置文件配置错误！");
			}
			return t;
	}
	
	public static Runner getRunner() {
		Runner runner = new Runner(local);
		return runner;
	}
}
